import { exec } from 'child_process';
import fs from 'fs';
import path, { ParsedPath } from 'path';
import { getRandomNumber } from '../globalUtils';
// nodejs 遍历文件夹
// 如果options只是一个路径地址的话，会直接遍历递归返回所有文件，不包括文件夹
// options.src 表示文件夹路径
// options.onlyFile 是否只需要返回文件路径列表，不需要文件夹路径列表
// options.level 循环层级必须大于0，不传，传0或传其他值表示一直递归
// 如果options只是个字符串的话，则相当于是 只传了 {src}
// const fs = require('fs');
// const path = require('path');
export interface EachDirOptionsType {
  src: string;
  onlyFile: boolean;
  level: number;
}
export interface EachDirItemType extends ParsedPath {
  src: string;
  type: string;
  [str: string]: any;
}
export function eachDir(options: string): EachDirItemType[];
export function eachDir(options: EachDirOptionsType): EachDirItemType[];
export function eachDir(options: any) {
  if (typeof options === 'string') {
    options = { src: options };
  }
  let { src: dirstr, onlyFile = true, level = 0 } = options;
  let arr: EachDirItemType[] = [];
  level = parseInt(level); // 最大层级
  level = level > 0 ? level : 0;
  aa(dirstr);
  function aa(dirs: string) {
    // 当前层级
    let dlevel =
      dirs
        .replace(dirstr, '')
        .split(/\/|\\/g)
        .filter((s) => s).length + 1;
    let list = fs.readdirSync(dirs);
    list.forEach((s) => {
      const src = path.join(dirs, s);
      let o = { src, type: 'file', ...path.parse(src) };
      let stat = fs.statSync(o.src);
      if (stat.isDirectory()) {
        if (onlyFile === false) {
          o.type = 'dir';
          arr.push(o);
        }
        if (level === 0 || level > dlevel) {
          // 文件夹
          aa(o.src);
        }
      } else {
        arr.push(o);
      }
    });
  }
  return arr;
}

// 获取媒体文件的数据
export async function getMetadata(src: string): Promise<{ duration: number; size: number }> {
  function fn(str: string) {
    const arr = (str + '').split('\n').map((s) => s.trim());
    const size = parseFloat(getValue(arr, 'size')) || 0;
    const duration = parseFloat(getValue(arr, 'duration')) || 0;
    return { size, duration };
  }
  function getValue(arr: string[], k: string) {
    return (arr.find((s) => s.startsWith(k)) || '').split('=').map((s) => s.trim())[1] || '';
  }
  return new Promise((res, rej) => {
    const command = `ffprobe -v error -i "${src}" -show_format`;
    exec(command, (error, stdout) => {
      if (error) {
        rej(error);
        return;
      }
      res(fn(stdout));
    });
  });
}

// 分割时间段
export function splitTimePeriod(duration: number, min: number, max: number): [number, number][] {
  if (!(min > 0 && max > 0)) {
    return [[0, duration]];
  }
  const arr: number[] = [0];
  function fn(balance: number) {
    if (balance > min + max) {
      const num = getRandomNumber(min, max);
      arr.push(arr[arr.length - 1] + num);
      fn(balance - num);
    } else {
      arr.push(arr[arr.length - 1] + balance);
    }
  }
  fn(duration);
  const result: [number, number][] = arr.slice(1).reduce((t: [number, number][], v, i, ar) => {
    t.push([i === 0 ? 0 : ar[i - 1], v]);
    return t;
  }, []);
  return result;
}

// 随机获取时间段里面的一段时间
export function getRandomTimePeriod(timePeriod: [number, number], min: number, max: number): [number, number] {
  const balance = timePeriod[1] - timePeriod[0];
  if (balance < min) {
    return [...timePeriod];
  }
  const duration = getRandomNumber(min, max);
  if (balance < duration) {
    return [...timePeriod];
  }
  const start = getRandomNumber(0, balance - duration) + timePeriod[0];
  return [start, start + duration];
}

// 获取一个或多个文件夹里的所有文件
// 多个换行分割
export function getAllFiles(inputDir: string): EachDirItemType[] {
  if (!(typeof inputDir === 'string' && inputDir)) {
    return [];
  }
  const dirs = inputDir
    .split('\n')
    .map((s) => s.trim())
    .filter(Boolean);
  const arr: EachDirItemType[] = [];
  dirs.forEach((dir) => {
    arr.push(...eachDir(dir.replace(/\\/g, '/')));
  });
  return arr;
}

// 截取单个视频
export interface ffVideoOneParamsType {
  inputFile: string;
  outputFile: string;
  start: string;
  duration: number | string;
}
export async function ffVideoOne(options: ffVideoOneParamsType) {
  const { inputFile, outputFile, start, duration } = options;
  fs.mkdirSync(path.parse(outputFile).dir, { recursive: true });
  return new Promise((res, rej) => {
    const command = `ffmpeg -i "${inputFile}" -ss ${start} -t ${duration} -c copy "${outputFile}"`;
    exec(command, (error, stdout) => {
      if (error) {
        rej(error);
        return;
      }
      res(stdout);
    });
  });
}
